package com.ccl.iot.updater;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnDismissListener;
import android.os.Handler;
import android.os.Message;

import com.ccl.iot.R;
import com.ccl.iot.publics.AppManager;
import com.ccl.iot.publics.Debugger;
import com.ccl.iot.publics.FileSystem;
import com.ccl.iot.publics.Res;
import com.ccl.iot.publics.StringFactory;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.ArrayList;

public class AppUpdater {
    public class AppInformation {
        public int iVersionCode = 0;
        public String iVersionName = null;
        public int iFileSize = 0;
        public ArrayList<Integer> iForceUpdateVersion = null;
        public String iDescription = null;
        public String iURL = null;
    }

    public interface AppUpdaterListener {
        public Context getContext();

        public boolean requestUpdate(AppInformation aApp);

        public void onUpdateCancel(AppInformation aApp);

        public void onStartUpdate(AppInformation aApp);

        public void onUpdateFailed(AppInformation aApp);
    }

    public final static int KUPDATE_NECESSITY_NO = 0;
    public final static int KUPDATE_NECESSITY_CAN = 1;
    public final static int KUPDATE_NECESSITY_FORCE = 2;


    public static void Initialize(Context aContext) {
        if (gDefault == null) {
            gDefault = new AppUpdater(aContext);
        }
        Res.AddString(aContext, R.string.Caption_Version, R.string.Caption_Size, R.string.Caption_UpdateContext);
    }

    private static AppUpdater gDefault = null;

    public static AppUpdater GetDefaultUpdater() {
        return gDefault;
    }

    public static String GetDefaultDownloadApp(Context aContext) {
        if (aContext != null) {
            String tmp = null;
            File externalCacheDir = aContext.getExternalCacheDir();
            tmp = externalCacheDir.getAbsolutePath() + "/app.apk";
            return tmp;
        }

        return null;
    }

    private Context iContext = null;
    private AppUpdaterListener iListener = null;

    private AppUpdater(Context aContext) {
        iContext = aContext;
    }

    private String getJSONString(JSONObject aObject, String aName, String aDefault) {
        if (aObject != null) {
            try {
                return aObject.getString(aName);
            } catch (JSONException e) {
            }
        }

        return aDefault;
    }

    public AppInformation getUpdateInfo() {
        try {
//            http://iot.cclcp.com:5499/Downloads/AppDebug/CCLIOT_debug.apk
            String tJSON = HttpHelper.GetHttpRequestString("http://iot.cclcp.com:5499/Downloads/App/ccliot.json");

            if (tJSON != null) {
                JSONArray tArray = new JSONArray(tJSON);

                if (tArray.length() > 0) {
                    JSONObject tObject = tArray.getJSONObject(0);

                    if (tObject != null) {
                        tArray = tObject.getJSONArray("Android");

                        if (tArray != null && tArray.length() > 0) {
                            tObject = tArray.getJSONObject(0);

                            if (tObject != null) {
                                int tCode = tObject.getInt("Code");

                                if (AppManager.GetPackageVersionCode(iContext) < tCode) {
                                    AppInformation tApp = new AppInformation();

                                    String tValue = getJSONString(tObject, "ForceUpdateVersion", null);

                                    if (tValue != null) {
                                        if (tValue.compareToIgnoreCase("all") == 0) {
                                            tApp.iForceUpdateVersion = new ArrayList<Integer>();

                                            //											for (int i = 0; i < tApp.iVersionCode; i++){
                                            //												tApp.iForceUpdateVersion.add(i);
                                            tApp.iForceUpdateVersion.add(-1);
                                            //											}
                                        } else if (tValue.length() > 0) {
                                            String tVersions[] = StringFactory.Split(tValue, "|");

                                            if (tVersions != null && tVersions.length > 0) {
                                                tApp.iForceUpdateVersion = new ArrayList<Integer>();

                                                for (int i = 0; i < tVersions.length; i++) {
                                                    tApp.iForceUpdateVersion.add(Integer.valueOf(tVersions[i]));
                                                }
                                            }
                                        }
                                    }

                                    tApp.iVersionCode = tCode;
                                    tApp.iVersionName = getJSONString(tObject, "Version", "Unknown");
                                    tApp.iFileSize = Integer.valueOf(getJSONString(tObject, "FileSize", "0"));
                                    tApp.iDescription = getJSONString(tObject, "Description", "None");
                                    tApp.iURL = getJSONString(tObject, "URL", "http://iot.cclcp.com:5499/Downloads/App/ccliot.apk");

                                    return tApp;
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private AppInformation iLastVersionAppInformation = null;

    private int getUpdateNecessity() {
        AppInformation tApp = getUpdateInfo();

        if (tApp != null) {
            iLastVersionAppInformation = tApp;

            if (tApp.iForceUpdateVersion != null && tApp.iForceUpdateVersion != null && (tApp.iForceUpdateVersion.contains(AppManager.GetPackageVersionCode(iContext)) || tApp.iForceUpdateVersion.contains(-1))) {
                return KUPDATE_NECESSITY_FORCE;
            } else {
                return KUPDATE_NECESSITY_CAN;
            }
        }

        return KUPDATE_NECESSITY_NO;
    }

    private void installApp() {
        AppManager.InstallApk(iListener.getContext(), GetDefaultDownloadApp(iContext));
    }

    private void onDownloadProgress(int aTotalSize, int aProgress) {
        iDownloadHandle.sendMessage(Message.obtain(iDownloadHandle, iDownloadHandle.hashCode(), aTotalSize, aProgress));
    }

    private void onDownloadComplete() {
        Debugger.Information("Download complete");

        iDownloadHandle.sendEmptyMessage(iDownloadHandle.hashCode() + 1);
    }

    private void onDownloadFailed() {
        Debugger.Information("Download failed");

        iDownloadHandle.sendEmptyMessage(iDownloadHandle.hashCode() + 2);
    }

    private DownloadDialog iDownloadDialog = null;
    private Handler iDownloadHandle = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg != null && iListener != null) {
                if (msg.what == this.hashCode()) {
                    if (msg.arg1 != msg.arg2) {
                        if (iDownloadDialog == null) {
                            iDownloadDialog = new DownloadDialog(iListener.getContext(), R.drawable.icon_app, Res.GetString(R.string.app_name), msg.arg1, true, false);

                            iDownloadDialog.show().setOnDismissListener(new OnDismissListener() {
                                @Override
                                public void onDismiss(DialogInterface dialog) {
                                    if (iDownloadDialog != null) {
                                        System.exit(0);
                                    }
                                }
                            });
                        }

                        iDownloadDialog.setProgress(msg.arg2);
                    } else {
                        if (iDownloadDialog != null) {
                            final DownloadDialog tDialog = iDownloadDialog;

                            iDownloadDialog = null;

                            tDialog.dismiss();
                        }
                    }
                } else if (msg.what == this.hashCode() + 1) {
                    installApp();
                } else if (msg.what == this.hashCode() + 2) {
                    new AlertDialog.Builder(iListener.getContext(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT).setTitle(R.string.Error_UpdateFailed).setMessage(R.string.UpdateRetryRequest)
                            .setPositiveButton(R.string.Retry, new OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    updateApp();

                                    dialog.dismiss();
                                }
                            }).setNegativeButton(R.string.Cancel, new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            iListener.onUpdateCancel(iLastVersionAppInformation);

                            System.exit(0);
                        }
                    }).show();
                }
            }
        }
    };

    private boolean iDownloading = false;

    private boolean downloadApp() {
        if (iListener != null && iLastVersionAppInformation != null && iDownloading == false) {
            iDownloading = true;

            iListener.onStartUpdate(iLastVersionAppInformation);

            new Thread(new Runnable() {
                @Override
                public void run() {
                    int tSize;
                    long tTime = System.currentTimeMillis();

                    tSize = HttpHelper.GetHttpRequestFile(iLastVersionAppInformation.iURL, GetDefaultDownloadApp(iContext), new HttpHelper.HttpDownloadListener() {
                        @Override
                        public void onDownloadProgress(int aSize, int aPos) {
                            AppUpdater.this.onDownloadProgress(aSize, aPos);
                        }
                    });

                    iDownloading = false;

                    if (tSize > 0) {
                        Debugger.Print("Last version app downloaded in " + (System.currentTimeMillis() - tTime) + "ms");

                        onDownloadComplete();
                    } else {
                        onDownloadFailed();
                    }
                }
            }).start();

            return true;
        }

        return false;
    }

    private boolean updateApp() {
        if (iListener != null && iDownloading == false) {
            if (FileSystem.FileExists(GetDefaultDownloadApp(iContext), false)) {
                if (AppManager.GetPackageVersionCode(iContext) == iLastVersionAppInformation.iVersionCode) {
                    onDownloadComplete();

                    return true;
                } else {
                    iDownloading = false;
                }
            }

            return downloadApp();
        }

        return false;
    }

    private void updateRequest(boolean aForce) {
        if (iListener != null) {
            if (iListener.requestUpdate(iLastVersionAppInformation) == false) {
                return;
            }
        }

        iUpdateHandle.sendMessage(Message.obtain(iUpdateHandle, iUpdateHandle.hashCode(), aForce ? 1 : 0, 0));
    }

    private Dialog iRequestDialog = null;
    private Handler iUpdateHandle = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == this.hashCode()) {
                java.lang.StringBuilder tInfo = new java.lang.StringBuilder();

                if (iLastVersionAppInformation != null) {
                    tInfo.append(Res.GetString(R.string.Caption_Version));
                    tInfo.append(iLastVersionAppInformation.iVersionName).append("\n");
                    tInfo.append(Res.GetString(R.string.Caption_Size));
                    tInfo.append(StringFactory.GetSizeDescription(iLastVersionAppInformation.iFileSize, 0)).append("\n");
                    tInfo.append(Res.GetString(R.string.Caption_UpdateContext)).append("\n");
                    tInfo.append(iLastVersionAppInformation.iDescription);
                }

                if (msg.arg1 == 0) {
                    iRequestDialog = new AlertDialog.Builder(iListener.getContext(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT).setTitle(R.string.NewVersionCanUpdate).setMessage(tInfo)
                            .setPositiveButton(R.string.Update, new OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    updateApp();

                                    iRequestDialog = null;

                                    dialog.dismiss();
                                }
                            }).setNegativeButton(R.string.Cancel, new OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();

                                    iRequestDialog = null;

                                    iListener.onUpdateCancel(iLastVersionAppInformation);
                                }
                            }).create();
                    if (!iRequestDialog.isShowing()) {
                        iRequestDialog.show();
                    }
                } else {
                    iRequestDialog = new AlertDialog.Builder(iListener.getContext(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT).setTitle(R.string.NewVersionNeedUpdate).setMessage(tInfo)
                            .setPositiveButton(R.string.Update, new OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    updateApp();

                                    iRequestDialog = null;

                                    dialog.dismiss();
                                }
                            }).show();

                    iRequestDialog.setCancelable(false);

                    iRequestDialog.setOnDismissListener(new OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialog) {
                            if (iRequestDialog != null) {
                                iRequestDialog = null;
                            }
                        }
                    });
                }
            }
        }
    };

    private boolean iChecking = false;

    public void checkUpdate(AppUpdaterListener aListener) {
        //if (Debug.isDebuggerConnected() == false){
        if (iChecking == false && iDownloading == false) {
            iListener = aListener;

            iChecking = true;

            new Thread(new Runnable() {
                @Override
                public void run() {
                    Debugger.Print("Start auto update check");

                    switch (getUpdateNecessity()) {
                        case KUPDATE_NECESSITY_CAN: {
                            Debugger.Error("New version " + iLastVersionAppInformation.iVersionName + " available for update");

                            updateRequest(false);

                            break;
                        }
                        case KUPDATE_NECESSITY_FORCE: {
                            Debugger.Error("New version " + iLastVersionAppInformation.iVersionName + " need to update");

                            updateRequest(true);

                            break;
                        }
                        default: {
                            if (iListener != null) {
                                iListener.onUpdateCancel(null);
                            }
                        }
                    }

                    iChecking = false;
                }
            }).start();
        }
        //}else if (aListener != null){
        //	aListener.onUpdateCancel(null);
        //}
    }
}
